package process_demo.review.about_singleton;

/**
 * @author haomin
 * @date 2022/09/11 17:43
 **/
class LazyModeV3 {
    // volatile
    private volatile static LazyModeV3 instance = null;

    public static LazyModeV3 getInstance(){
        // 1. 第一次调用这个方法时，说明我们应该实例化对象了
        if (instance == null) {
            // 在第一次instance 没有初始化的时候
            // 没有锁保护，有多个线程可以走到这里 a, b, c, d

            // 2. **但是只有第一个线程a能加锁，a 加锁后并且实例化对象，
            //    **b, c, d 加锁进去后发现instance != null, 就不会再创建了
            synchronized (LazyModeV3.class) {
                // 3. 加锁之后才能执行
                // 第一个抢到锁的线程看instance 是 null
                // 其他第一个抢到锁的线程看instance 是 null
                // 保证instance 只实例化一次
                if (instance == null) {
                    instance = new LazyModeV3();    // 只在第一次的时候执行

                    // 4. 但是还可能出问题，出现重排序，变成 1 -> 3 -> 2 其他线程掉instance就出现问题，
                    // 所以定义时就加上volatile，防止重排序;
                }
            }
        }
        return instance;
    }

    private LazyModeV3(){};
}